#pragma once

#include <gtl/smart_ptr/deleter.h>
#include <gtl/type/type.h>

namespace gtl
{

template<class T, class Deleter = deleter::handle_ref>
class handler
{
public:
	typedef handler<T, Deleter> self_type;

public:
	handler() : m_handler(NULL)
	{
	}

	handler(T h) : m_handler(h)
	{
	}

	~handler()
	{
		release();
	}

	handler& operator=(T h)
	{
		release();
		m_handler = h;
		return *this;
	}

	T detach()
	{
		handler h = m_handler;
		m_handler = NULL;
		return h;
	}

	T get() const
	{
		return m_handler;
	}

	void swap(handler<T>& other)
	{
		std::swap(m_handler, other.m_handler);
	}

	void reset()
	{
		self_type().swap(*this);
	}

	void reset(T h)
	{
		self_type(h).swap(*this);
	}

	operator T() const
	{
		return m_handler;
	}

	operator T&()
	{
		return m_handler;
	}

	T* operator&()
	{
		return &m_handler;
	}

	T* operator&() const
	{
		return &m_handler;
	}

	typename gtl::type::ptr<T>::type operator->()
	{
		return gtl::type::ptr<T>::value(m_handler);
	}

	typename gtl::type::ptr<T>::type operator->() const
	{
		return gtl::type::ptr<T>::value(m_handler);
	}

protected:
	void release()
	{
		Deleter()(&m_handler);
		m_handler = NULL;
	}

protected:
	handler(const handler<T>& h);
	handler& operator=(const handler<T>& r);

protected:
	T m_handler;
};

typedef handler<HANDLE, gtl::deleter::handle_ref> handle;

} // end of namespace gtl